// 14 重载运算与类型转换
/**
 * 当运算符被用于类类型的对象时，C++语言允许我们为其指定新的含义；同时，我们也能自定义类类型之间的转换规则。和内置类型的转换一样，类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。
 * 当运算符作用于类类型的运算对象时，可以通过运算符重载重新定义该运算符的含义。明智地使用运算符重载能令我们的程序更易于编写和阅读。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <memory>
#include <new>
using namespace std;
#include "../Chapter13/13.5.cc" // 不能编译，因为重复定义的main函数
#include "../Chapter12/12.1.6.cc" // 不能编译，因为重复定义的main函数
#include <functional>

// 最好不要在两个类之间构建相同的类型转换
struct B;
struct A
{
    A() = default; // 默认构造函数
    A(const B&);   // 把一个B转换成A（隐式转换机制）
    // 其他数据成员
};
struct B
{
    operator A() const; // 也是把一个B转换成A（类型转换运算符）
    // 其他数据成员
};
A f(const A&);
B b;
A a = f(b); // 二义性错误，含义是f(B::operatorA()) 还是f(A::A(const B&)) ？

int main()
{
    // 14.9 重载、类型转换与运算符
    // 在7.5.4节（第263页）中我们看到由一个实参调用的非显式构造函数定义了一种隐式的类型转换，这种构造函数将实参类型的对象转换成类类型。
    // 我们同样能定义对于类类型的类型转换，通过定义类型转换运算符可以做到这一点。
    // 转换构造函数和类型转换运算符共同定义了类类型转换（class-type conversions），这样的转换有时也被称作用户定义的类型转换（user-defined conversions）。

    // 14.9.3 函数匹配与重载运算符
    // 重载的运算符也是重载的函数。因此，通用的函数匹配规则（参见6.4节，第208页）同样适用于判断在给定的表达式中到底应该使用内置运算符还是重载的运算符。
    // 表达式中运算符的候选函数集既应该包括成员函数，也应该包括非成员函数。
    // 如果我们对同一个类既提供了转换目标是算术类型的类型转换，也提供了重载的运算符，则将会遇到重载运算符与内置运算符的二义性问题。


    return 0;
}